-module(util).
-include("common.hrl").
%%===============时间 操作=======================
-export([
	now/0,
	now_mili/0,
	datetime_to_seconds/1,
	seconds_to_datetime/1,
	isThroughHourBetweenTimestamp/3
]).
%%===============ETS 操作=======================
-export([
	ets_foreach_key/2,
	ets_all_key/1,
	ets_foreach_return/4,
	ets_sub_keyList/2,
	ets_sub_keyList/3,
	getEtsElement/4
]).
%%===============LIST 操作=======================
-export([
	foldl/3,
	shuffle_list_quick/1,
	shuffle_list/1,
	list_fun_take/2,
	list_fun_find/2,
	list_fun_replace/3,
	list_nth_replace/3,
	list_nth_take/2,
	list_is_duplicate/1,
	list_map/2,
	listSelect/2,
	getValueInSectionList/3,
	term_to_list/1,
	listFunReturn/4,
	listKeyReplaceElement/5,
	listDelByKeyList/2,
	getValueByKey/2,getValueByKey/3,getValueByKey/4,
	listKeyStoreList/3,
	listDelDuplicate/1,listDelDuplicate/2,
	calcRankUpdate/9
]).
%%---偏string操作---
-export([
	term_to_string/1,
	term_to_bitstring/1,
	string_to_term/1,
	bitstring_to_term/1,
	stringFuzzyMatch/2,
	format_utf8/1
]).
%%---偏权重---
-export([
	get_total_weight/1,
	random_weight_list_duplicate/2,
	random_weight_list/2,
	random_one_from_weight_list/1,
	random_list/2,
	random_one_from_list/1
]).
%%===============其他 操作=======================
-export([
	root_dir/0,
	md5/1,
	ceil/1,
	for/3,for_acc/4,for_map/3,
	element_pos/2,
	random_int/2,
	read_timer/1,
	ip_to_str/1,
	gen_random_seed/0,
	latin1/1,
	check_blankName/1,
	calc_name_length/1,
	getProcDictDataProperty/3,
	updateProcDictDataProperty/2,
	updateProcDictDataProperty/3,
	tupleAdd/3,
	make_proto/1,
	bool2int/1,int2bool/1,
	tryString2int/1,
	json2Term/1,
	roleRegName/1,roomRegName/1,
	reverseTuple/1,
	decimal/1,decimal/2,
	specialTruncRound/1,
	dropRecordName/1,attachRecordName/2,
	eval/1,getServerID/0
]).


-define(GREGORIAN_INTERVIAL_TIME,  (calendar:datetime_to_gregorian_seconds(data_setting:get(time_zone)))).


%% @doc 获取服务器根目录
root_dir() ->
	filename:dirname(filename:dirname(element(2,code:is_loaded(?MODULE)))).



%% @doc 取得当前的unix时间戳,单位：秒
now() ->
	{M,S,_} = os:timestamp(),
	M * 1000000 + S.

%% @doc 当前时间戳，单位：毫秒
now_mili() ->
	{M, S, Ms} = os:timestamp(),
	M * 1000000000 + S*1000 + Ms div 1000.

%% 转换成HEX格式的md5
md5(S) ->
	lists:flatten([io_lib:format("~2.16.0b",[N]) || N <- binary_to_list(erlang:md5(S))]).

%%向上取整
ceil(N) ->
	T = trunc(N),
	?IF(N =< T,T,T+1).

%% for循环
for(Max, Max, F) ->
	F(Max);
for(I, Max, F)  when I =< Max ->
	F(I),
	for(I+1, Max, F);
for(_I, _Max, _F) ->
	nil.

%% 带传入参数的for循环
%% @return Acc
for_acc(Max, Min, _F, Acc) when Min<Max -> Acc;
for_acc(Max, Max, F, Acc) -> F(Max, Acc);
for_acc(I, Max, F, Acc)   -> NewAcc = F(I, Acc), for_acc(I+1, Max, F, NewAcc).

for_map(Max,Max,F) -> [F(Max)];
for_map(I,Max,F)when I < Max -> [F(I)|for_map(I+1,Max,F)];
for_map(_,_,_) -> [].

%% term序列化，term转换为string格式，e.g., [{a},1] => "[{a},1]"
term_to_string(Term) ->
	binary_to_list(list_to_binary(io_lib:format("~w", [Term]))).

%% term序列化，term转换为bitstring格式，e.g., [{a},1] => <<"[{a},1]">>
term_to_bitstring(Term) ->
	erlang:list_to_bitstring(io_lib:format("~p", [Term])).

%% term反序列化，string转换为term，e.g., "[{a},1]"  => [{a},1]
string_to_term(String) ->
	case erl_scan:string(String++".") of
		{ok, Tokens, _} ->
			case erl_parse:parse_term(Tokens) of
				{ok, Term} -> Term;
				_Err -> ?UNDEFINED
			end;
		_Error ->
			?UNDEFINED
	end.

%% term反序列化，bitstring转换为term，e.g., <<"[{a},1]">>  => [{a},1]
bitstring_to_term(?UNDEFINED) -> ?UNDEFINED;
bitstring_to_term(BitString) ->
	string_to_term(binary_to_list(BitString)).

datetime_to_seconds({_Date,_Time}=Datetime)->
    calendar:datetime_to_gregorian_seconds(Datetime)
        - ?GREGORIAN_INTERVIAL_TIME.

seconds_to_datetime(MTime)->
    calendar:gregorian_seconds_to_datetime( 
      ?GREGORIAN_INTERVIAL_TIME+ MTime).

foldl(_F, {return,Acc}, _L) ->
    Acc;
foldl(F, Acc, [Tail|L]) ->
    foldl(F,F(Tail,Acc), L);
foldl(F, Acc, []) when is_function(F,2)->
    Acc.

%% 获得权值列表总权重
get_total_weight(List) ->
	get_total_weight(List,0).

%% 从一个带权重的列表中随机选取SelectNum个元素，可以相同
random_weight_list_duplicate(List, SelectNum) ->
	TotalWeight = get_total_weight(List),
	random_weight_list_duplicate2(List, SelectNum, TotalWeight, []).

random_weight_list_duplicate2(_List, 0, _, Result) ->
	Result;
random_weight_list_duplicate2(List, SelectNum, TotalWeight, Result) ->
	Random = rand:uniform() * TotalWeight,
	Element =
	foldl(fun({UnitWeight, _}=Ele, Acc) ->
						if UnitWeight + Acc > Random ->
							   {return, Ele};
						   ?TRUE ->
							   Acc + UnitWeight
						end
		  end, 0, List),
	random_weight_list_duplicate2(List, SelectNum -1, TotalWeight, [Element| Result]).


%% 从一个带权重的列表List中随机选取SelectNum个不同元素，结果列表顺序随机
%% weight_list:  [{weight1, value1}, {weight2, value2}]
random_weight_list(List, SelectNum) ->
	Len = length(List),
	TotalWeight = get_total_weight(List,0),
	if Len =< SelectNum ->
		   List;
	   ?TRUE ->
		   random_weight_list(List, SelectNum, TotalWeight, [])
	end.

random_weight_list(_List, 0, _, Result) ->
	Result;
random_weight_list(List, SelectNum, TotalWeight, Result) ->
	Random = rand:uniform() * TotalWeight,
	{Weight, _} = Element =
	foldl(fun({UnitWeight, _}=Ele, Acc) ->
						if UnitWeight + Acc > Random ->
							   {return, Ele};
						   ?TRUE ->
							   Acc + UnitWeight
						end
		  end, 0, List),
	NewList = lists:delete(Element, List),
	random_weight_list(NewList, SelectNum -1, TotalWeight - Weight, [Element| Result]).

%%从权重列表中，默认取一个随机的值
random_one_from_weight_list(WeightList) ->
	List = random_weight_list(WeightList,1),
	element(2,hd(List)).
	
random_one_from_list(List) ->
	Value = rand:uniform(length(List)),
	lists:nth(Value,List).

get_total_weight([], Weight) ->
	Weight;
get_total_weight([{WeightUnit, _} | Rest], Weight) ->
	get_total_weight(Rest, Weight + WeightUnit).


shuffle_list_quick(List) ->
    [Elem||{_,Elem}<-lists:keysort(1, [{rand:uniform(), Elem}||Elem<-List])].
%% 将List的中元素随机排列
shuffle_list(List) ->
    shuffle_list(List, erlang:length(List), []).

shuffle_list([], 0, RandomList) ->
    RandomList;
shuffle_list(List, Len, AccRandomList) ->
    Elem = lists:nth(rand:uniform(Len), List),
    shuffle_list(lists:delete(Elem, List), Len - 1, [Elem|AccRandomList]).
	
%% 从列表List中随机选取SelectNum个元素，组成新的列表，新列表的元素排列顺序与其在List中顺序相同
random_list(List, SelectNum) ->
	Len = length(List),
	if Len =< SelectNum ->
		   List;
	   true ->
		   random_list(List, SelectNum, Len, [])
	end.

random_list(_, 0, _, Result) ->
	lists:reverse(Result);
random_list([Head| Rest], SelectNum, Len, Result) ->
	case rand:uniform() =< SelectNum / Len of
		true ->
			random_list(Rest, SelectNum-1, Len-1, [Head|Result]);
		false ->
			random_list(Rest, SelectNum, Len-1, Result)
	end.

%% 计算一个元素在一个列表或tuple中第一次出现的位置
%% 元素在集合中不存在时，返回0
element_pos(Element, List) when is_list(List) ->
	element_pos(Element, List, 1);
element_pos(Element, Tuple) when is_tuple(Tuple) ->
	element_pos(Element, tuple_to_list(Tuple), 1);
element_pos(_, _) ->
	0.

element_pos(Element, [Element|_Rest], Index) ->
	Index;
element_pos(Element, [_|Rest], Index) ->
	element_pos(Element, Rest, Index+1);
element_pos(_, [], _) ->
	0.

%% 从[Lower...Higher]包括边界的整数区间中随机一个数
random_int(Lower, Higher) when Lower =< Higher ->
	rand:uniform(Higher -Lower+1) +Lower-1;
random_int(Higher, Lower) ->
	random_int(Lower, Higher).

list_fun_take(F,L) ->
    list_fun_take(F, L, []).

list_fun_take(F, [H|T], L)  ->
	case F(H) of
		?TRUE ->
    		{value, H, lists:reverse(L, T)};
		?FALSE ->
    		list_fun_take(F, T, [H|L])
	end;
list_fun_take(_F, [], _L) -> ?FALSE.

list_fun_find(_F,[]) ->
	?FALSE;
list_fun_find(F,[E|Rest]) ->
	case F(E) of
		?TRUE ->
			E;
		_ ->
			list_fun_find(F,Rest)
	end.

list_fun_replace(F, [Tup|Tail], New) ->
	case F(Tup) of
		?TRUE ->
    		[New|Tail];
		_ ->
			[Tup|list_fun_replace(F, Tail, New)]
	end;
list_fun_replace(_F, [], _) -> [].

%% 替换第n个
list_nth_replace(_, [], Info) ->
	[Info];
list_nth_replace(1, [_|T], Info) ->
	[Info|T];
list_nth_replace(N, List, Info) ->
	case N < 1 of
		?TRUE ->
			List;
		_ ->
			list_nth_replace(N, List, Info, [])
	end.
list_nth_replace(_N, [], Info, Head) ->
    lists:reverse(Head) ++ [Info];
list_nth_replace(1, [_|Rest], Info, Head) ->
    lists:reverse(Head) ++ [Info|Rest];
list_nth_replace(N, [H|T], Info, Head) ->
    list_nth_replace(N - 1, T, Info, [H|Head]).

%% 读timer 返回该timerRef剩余发送消息的时间(ms毫秒)
read_timer(Timer) when is_reference(Timer)->
	case erlang:read_timer(Timer) of
		?FALSE ->
			0;
		A ->
			A
	end;
read_timer(_) ->
	0.

%% 判断列表中是否有重复项
list_is_duplicate(List) ->
	list_is_duplicate(List, []).

list_is_duplicate([], _) ->
	?FALSE;
list_is_duplicate([H|T], List) ->
	case lists:member(H, List) of
		?TRUE ->
			?TRUE;
		?FALSE ->
			list_is_duplicate(T, [H|List])
	end.

%% 类似lists:keytake
%% return: {value, NthVar, T} | false
list_nth_take(N, List) ->
	list_nth_take(N, List, []).
list_nth_take(1, [NthVar|Tail], Temp) ->
	{value, NthVar, lists:reverse(Temp, Tail)};
list_nth_take(_N, [], _Temp) ->
	?FALSE;
list_nth_take(N, [Hd | Tail], Temp) ->
	list_nth_take(N-1, Tail, [Hd|Temp]).

%% 遍历ets的所有key
ets_foreach_key(Fun, Table) ->
    ets:safe_fixtable(Table, true),
    First = ets:first(Table),
    try
        do_ets_foreach_key(Fun, First, Table)
    after
	ets:safe_fixtable(Table, false)
    end.

do_ets_foreach_key(F, Key, Table) ->
    case Key of
	'$end_of_table' ->
	    ok;
	_ ->
	    F(Key),
		do_ets_foreach_key(F, ets:next(Table, Key), Table)
	end.
%% 获取ets所有key
ets_all_key(Table) ->
    ets:safe_fixtable(Table, true),
    First = ets:first(Table),
    try
        do_ets_all_key(First, Table, [])
    after
	ets:safe_fixtable(Table, false)
    end.

do_ets_all_key(Key, Table, Result) ->
    case Key of
	'$end_of_table' ->
	    Result;
	_ ->
		do_ets_all_key(ets:next(Table, Key), Table, [Key|Result])
	end.

%%当函数F执行ETS满足ConditionValue时，返回该Key值
ets_foreach_return(Table, F, ConditionValue,DefaultValue) ->
	ets:safe_fixtable(Table, true),
	First = ets:first(Table),
	try
		do_ets_foreach_return(F, First, Table,ConditionValue,DefaultValue)
	catch
		_:_ ->
			ets:safe_fixtable(Table, false),
			DefaultValue
	end.
do_ets_foreach_return(F, Key, Table,ConditionValue,DefaultValue) ->
	case Key of
		'$end_of_table' ->
			DefaultValue;
		_ ->
			case F(Key) of
				ConditionValue -> Key;
				_ -> do_ets_foreach_return(F, ets:next(Table, Key), Table,ConditionValue,DefaultValue)
			end
	end.

%%获取ETS中从指定序号开始，获取指定长度的Key的List
ets_sub_keyList(Table,StartIndex) ->
	ets_sub_keyList(Table,StartIndex,ets:info(Table,size)).
ets_sub_keyList(Table,StartIndex,Length) ->
	ets:safe_fixtable(Table, true),
	First = ets:first(Table),
	R = do_ets_sub_keyList(Table,First,StartIndex,Length,1,[]),
	ets:safe_fixtable(Table, false),
	R.
do_ets_sub_keyList(Table,Key,StartIndex,Length,CurIndex,R)when is_integer(Length),Length>0 ->
	case Key of
		'$end_of_table' ->
			R;
		_ ->
			case CurIndex >= StartIndex of
				?TRUE ->%%开始加入返回列表
					case CurIndex - StartIndex >= Length of
						?TRUE ->
							R;
						_ ->
							do_ets_sub_keyList(Table,ets:next(Table, Key),StartIndex,Length,CurIndex+1,[Key|R])
					end;
				_ ->
					do_ets_sub_keyList(Table,ets:next(Table, Key),StartIndex,Length,CurIndex+1,R)
			end
	end;
do_ets_sub_keyList(_Table,_Key,_StartIndex,_Length,_CurIndex,R) ->
	R.

%% @doc convert IP(tuple) to string()
ip_to_str(IP) ->
    case IP of
        {A, B, C, D} ->
            lists:concat([A, ".", B, ".", C, ".", D]);
        {A, B, C, D, E, F, G, H} ->
            lists:concat([A, ":", B, ":", C, ":", D, ":", E, ":", F, ":", G, ":", H]);
        Str when is_list(Str) ->
            Str;
        _ ->
            []
    end.

%% @doc 简单的mapreduce,仅供脚本使用
%%L中的所有元素执行F(X)然后返回列表 类似 lists:map
list_map(F, L) ->
	Parent = self(),
	Ref = make_ref(),
	[receive
		 {Ref,  Result} ->
			 Result 
	 end || _ <- [spawn(fun() -> Parent ! {Ref, F(X)} end)	
		 	|| X<-L]]. 

gen_random_seed() ->
	os:timestamp().

latin1(Name) ->
	Name2 = 
	if is_binary(Name) ->
		   binary_to_list(Name);
	   ?TRUE ->
		   Name
	end,
	Name3 = 
		case is_name_en(Name2) of
			?TRUE ->
				Name2;
			?FALSE ->
				unicode:characters_to_binary(Name2)
		end,
	Name3.

is_name_en(Name)->
	lists:all(fun(E)-> E =< 255 end, Name).

%% 输入的list为已经解码的utf8 list，检查字符串，只能为数字、大小写英文字母和汉字
check_blankName([]) ->
    true;
check_blankName([H|T]) ->
    case (H >=48 andalso H =< 57) orelse (H >=65 andalso H =< 90) orelse (H >=97 andalso H =< 122) orelse (H >= 16#4e00 andalso H =< 16#9fa5) of
        false ->
            false;
        true ->
            check_blankName(T)
    end.

%% 输入的list为已经解码的utf8 list，计算长度，汉字长度为2
calc_name_length(DecodeList) ->
    lists:foldr(fun(Val, Acc) ->
                    if
                        Val >= 16#10000 ->
                            Acc + 4;
                        Val >= 16#800 ->
                            Acc + 3;
                        Val >= 16#80 ->
                            Acc + 2;
                        true ->
                            Acc + 1
                    end
                end, 0, DecodeList).

getProcDictDataProperty(DictName, PropertyIndex, DefaultValue) ->
	Data = get(DictName),
	case ?CATCH(element(PropertyIndex,Data)) of
		{'EXIT',_} -> DefaultValue;
		Value -> Value
	end.
updateProcDictDataProperty(DictName, PropertyIndex, NewValue) ->
	Data = get(DictName),
	case ?CATCH(setelement(PropertyIndex,Data,NewValue)) of
		{'EXIT',_} -> ok;
		NewData -> put(DictName, NewData)
	end.
updateProcDictDataProperty(DictName,List) ->
	lists:foreach(fun({PropertyIndex, NewValue}) -> updateProcDictDataProperty(DictName, PropertyIndex, NewValue) end,List).

listSelect(Conditions, List) ->
	lists:filter(fun(Data) -> lists:all(fun({Index,Value}) -> element(Index,Data) == Value end, Conditions) end, List).

tupleAdd(Tuple1, Tuple2, FromPos) ->
	tupleAdd(Tuple1, Tuple2, FromPos, tuple_size(Tuple1), Tuple1).
tupleAdd(Tuple1, Tuple2, EndPos, EndPos, Tuple) ->
	V = element(EndPos,Tuple1) + element(EndPos,Tuple2),
	setelement(EndPos,Tuple,V);
tupleAdd(Tuple1, Tuple2, FromPos, EndPos, Tuple) when FromPos < EndPos ->
	V = element(FromPos,Tuple1) + element(FromPos,Tuple2),
	NewTuple = setelement(FromPos,Tuple,V),
	tupleAdd(Tuple1,Tuple2,FromPos+1,EndPos,NewTuple).

make_proto([FileNameAtom]) ->
	FullName = atom_to_list(FileNameAtom),
	Path = filename:dirname(FullName),
	OnlyFileName = filename:basename(FullName, ".proto"),
	IndexStr = string:substr(OnlyFileName, 1, 3),
	StartIndex = list_to_integer(IndexStr ++ "01"),
	FileName = FullName,
	FileName2 = Path ++ "\\" ++ OnlyFileName ++ "2.proto",
	{ok, IO} = file:open(FileName, [read]),
	FileContent1 = clean_proto_file(IO, "", {?FALSE, ""}),
	%%Args::{协议序号，字段序号}
	FileContent = read_proto_file(FileContent1, "", {StartIndex, 1, ?TRUE}),
	file:write_file(FileName2, FileContent, [write]),
	file:close(IO),
	io:format("delete ~p~n",[file:delete(FileName)]),
	io:format("rename ~p~n",[file:rename(FileName2,FileName)]),
	halt(),
	ok.
%%自动编号
read_proto_file([], File2, {_ProtoIndex, _WordIndex, _IsWrapLine}) ->
	File2;
read_proto_file([Term1 | T], File2, {ProtoIndex, WordIndex, IsWrapLine}) ->
	Term = hd(io_lib:format("~ts",[[Term1]])),
	{AddTerm, NewProtoIndex, NewWordIndex, NewIsWrapLine} =
		case Term of
			"[" -> {"[id=" ++ integer_to_list(ProtoIndex), ProtoIndex + 1, WordIndex, IsWrapLine};
			";" ->
				case IsWrapLine of
					?TRUE -> {"=" ++ integer_to_list(WordIndex) ++ ";", ProtoIndex, WordIndex + 1, ?FALSE};
					_ -> {Term, ProtoIndex, WordIndex, IsWrapLine}%%注释里面的分号
				end;
			"}" -> {Term, ProtoIndex, 1, IsWrapLine};
			"\n" -> {Term, ProtoIndex, WordIndex, ?TRUE};
			_ -> {Term, ProtoIndex, WordIndex, IsWrapLine}
		end,
	read_proto_file(T, File2 ++ AddTerm, {NewProtoIndex, NewWordIndex, NewIsWrapLine}).
%%清除老的编号
clean_proto_file(IO, File2, {IsCollectContent, TempDelContent}) ->
	case io:get_chars(IO, '', 1) of
		eof -> File2;
		{error, ErrorDescription} ->
			io:format("ErrorDescription=~p~n", [ErrorDescription]),
			File2;
		Term ->
			{AddTerm, NewDelContent, NewIsCollectContent} =
				case Term of
					"[" -> {Term, "", ?TRUE};
					"=" ->
						case IsCollectContent of
							?TRUE -> {"", TempDelContent ++ Term, IsCollectContent};
							_ -> {"", Term, ?TRUE}
						end;
					"]" ->
						case IsCollectContent of
							?TRUE -> {Term, "", ?FALSE};
							_ -> {Term, TempDelContent, IsCollectContent}
						end;
					"\n" ->
						case IsCollectContent of
							?TRUE -> {TempDelContent ++ Term, "", ?FALSE};
							_ -> {Term, TempDelContent, IsCollectContent}
						end;
					";" ->
						case IsCollectContent of
							?TRUE -> {Term, "", ?FALSE};
							_ -> {Term, TempDelContent, IsCollectContent}
						end;
					_ ->
						case IsCollectContent of
							?TRUE -> {"", TempDelContent ++ Term, IsCollectContent};
							_ -> {Term, TempDelContent, IsCollectContent}
						end
				end,
			clean_proto_file(IO, File2 ++ AddTerm, {NewIsCollectContent, NewDelContent})
	end.

%%列表元素，区间获取值
%%List::[{Section, Value}]
%%Key >= Section
%%return Value
getValueInSectionList(Key, [{_Min,_Max,_Value}|_]=List, DefaultValue) ->
	Func = fun({Min, Max, Value}, Acc) ->
		case Key >= Min andalso Key =< Max of
			?TRUE -> Value;
			_ -> Acc
		end
	       end,
	lists:foldl(Func, DefaultValue, List);
getValueInSectionList(Key, [{{_Min,_Max},_Value}|_]=List, DefaultValue) ->
	Func = fun({{Min, Max}, Value}, Acc) ->
		case Key >= Min andalso Key =< Max of
			?TRUE -> Value;
			_ -> Acc
		end
	       end,
	lists:foldl(Func, DefaultValue, List);
getValueInSectionList(Key, [{_Section,_Value}|_]=List, DefaultValue) ->
	SortedList = lists:keysort(1,List),
	Func = fun({Section, Value}, Acc) ->
		case Key >= Section of
			?TRUE -> Value;
			_ -> Acc
		end
		end,
	lists:foldl(Func, DefaultValue, SortedList);
getValueInSectionList(_Key,_,DefaultValue) ->
	DefaultValue.

tryString2int(Str) ->
	try
		erlang:list_to_integer(Str)
	catch
		_:_Why -> Str
	end.
term_to_list(X) when is_integer(X) -> integer_to_list(X);
term_to_list(X) when is_float(X)   -> float_to_list(X);
term_to_list(X) when is_atom(X)    -> atom_to_list(X);
term_to_list(X) when is_binary(X)  -> binary_to_list(X);
term_to_list(X) when is_list(X)    -> X.

getEtsElement(Table,Key,Pos,DefaultValue) ->
	try
	    ets:lookup_element(Table,Key,Pos)
	catch
	    _:_  -> DefaultValue
	end.

%%将json字符串尝试转换成erlang元素
%%json的key值，不加入最终元素
json2Term(String) ->
	try
		{ok,List,_}=erl_scan:string(String),
		json2Term(List,"",key)
	catch
		_:Why:Stack ->
			?ERR("json2Term String=~p,Why=~p,Stack=~p", [String, Why, Stack]),
			[]
	end.
json2Term([], R, _) ->
	{ok, Scan1, _} = erl_scan:string(R ++ "."),
	{ok, P} = erl_parse:parse_exprs(Scan1),
	{value, Value, _} = erl_eval:exprs(P, []),
	Value;
json2Term([Tuple | T], R, Flag) ->
	{NewR, NewFlag} = case Tuple of
		                            {'{', _} -> {R ++ "{", key};
		                            {string, _, Str} -> case Flag of
			                                                key -> {R, value};
			                                                _ -> {R ++"\""++ Str++"\"", key}
		                                                end;
		                            {':', _} -> {R, value};
		                            {',', _} -> {R++",", key};
		                            {'[', _} -> {R ++ "[", value};
		                            {integer, _, Int} -> {R ++ integer_to_list(Int), key};
		                            {atom, _, Atom} -> {R ++ atom_to_list(Atom), key};
		                            {'}', _} -> {R ++ "}", key};
		                            {']', _} -> {R ++ "]", key};
		                            {'-',_}->{R++"-",value};
		                            {float,_,Float} -> {R++integer_to_list(trunc(Float)),key};
		                            Other -> ?ERR("json2Term Other=~p", [Other]), {R, Flag}
	                            end,
	json2Term(T, NewR, NewFlag).

roleRegName(RoleID) ->
	list_to_atom("role_"++integer_to_list(RoleID)).
roomRegName(RoomID) ->
	list_to_atom("room_"++integer_to_list(RoomID)).

%%从列表中判断，当达到某个条件时，就停止，并且返回函数值
listFunReturn(_Fun, _Condition, [], DefaultValue) ->
	DefaultValue;
listFunReturn(Fun, Condition, [Arg|T], DefaultValue) ->
	case Fun(Arg) of
		{Condition,FunRet} -> FunRet;
		_ -> listFunReturn(Fun,Condition,T,DefaultValue)
	end.

int2bool(1) -> ?TRUE;
int2bool(0) -> ?FALSE.
bool2int(?TRUE) -> 1;
bool2int(?FALSE) -> 0.

%%lists:keyreplace的扩展 只更新元组中其中一个元素
%%return NewList
listKeyReplaceElement(Key,KeyIndex,List,ElementIndex,Value) ->
	Tuple = lists:keyfind(Key,KeyIndex,List),
	Tuple1 = setelement(ElementIndex,Tuple,Value),
	lists:keyreplace(Key,KeyIndex,List,Tuple1).

%%像对调列表一样，对调元组
reverseTuple(Tuple) ->
	List = tuple_to_list(Tuple),
	RList = lists:reverse(List),
	list_to_tuple(RList).

%%删除列表中 Key在KeyList的元素
listDelByKeyList(List,KeyList) ->
	[Data||Data<-List,not lists:member(element(1,Data),KeyList)].

%%保留Value,Decimal位小数
decimal(Value) ->
	decimal(Value,2).
decimal(Value,Decimal) ->
	Base = math:pow(10,Decimal),
	trunc(Value*Base)/Base.
%%四舍五入
specialTruncRound(Value) ->
	ValueInt = trunc(Value),
	R = (Value - ValueInt) >=0.5,
	?IF(R,ValueInt+1,ValueInt).

getValueByKey(List,Key) ->
	getValueByKey(List,Key,1,0).
getValueByKey(List,Key,KeyIndex) ->
	getValueByKey(List,Key,KeyIndex,0).
getValueByKey(List,Key,KeyIndex,DefaultValue) ->
	case lists:keyfind(Key,KeyIndex,List) of
		{_,Value} -> Value;
		_ -> DefaultValue
	end.

%%检测两个时间戳中间，是否穿过了某个时间点
isThroughHourBetweenTimestamp(Time1,Time2,Hour)when Time1<Time2 ->
	{Date1,{Hour1,_,_}}=seconds_to_datetime(Time1),
	{Date2,{Hour2,_,_}}=seconds_to_datetime(Time2),
	case Date1=/=Date2 of
		?TRUE ->%%不在同一天
			Hour1<Hour orelse Hour =< Hour2;
		_ ->
			Hour1<Hour andalso Hour=<Hour2
	end;
isThroughHourBetweenTimestamp(Time1,Time2,Hour)when Time1>Time2 ->
	isThroughHourBetweenTimestamp(Time2,Time1,Hour);
isThroughHourBetweenTimestamp(_Time1,_Time2,_Hour) ->
	?FALSE.

%%将List1和List2连接，相同的部分取List1的值
listKeyStoreList(List1,List2,KeyIndex) ->
	lists:foldl(
		fun(Record,AccList) ->
			Key = element(KeyIndex,Record),
			case lists:keymember(Key,KeyIndex,AccList) of
				?TRUE -> AccList;
				_ -> [Record|AccList]
			end
		end,List1,List2).
%%通过KeyIndex检测List中重复的键，如果KeyIndex为0，则表示元素整个匹配才算重复
listDelDuplicate(List) ->
	listDelDuplicate(List,0).
listDelDuplicate(List,KeyIndex) ->
	listDelDuplicate_1(List,KeyIndex,[]).
listDelDuplicate_1([],_,R) ->
	R;
listDelDuplicate_1([Data|T],KeyIndex,R)when KeyIndex=<0 ->
	case lists:member(Data,R) of
		?TRUE -> listDelDuplicate_1(T,KeyIndex,R);
		_ -> listDelDuplicate_1(T,KeyIndex,[Data|R])
	end;
listDelDuplicate_1([Data|T],KeyIndex,R) ->
	case lists:keymember(element(KeyIndex,Data),KeyIndex,R) of
		?TRUE -> listDelDuplicate_1(T,KeyIndex,R);
		_ -> listDelDuplicate_1(T,KeyIndex,[Data|R])
	end.

%%字符串模糊查询
stringFuzzyMatch("", "") ->
	?TRUE;
stringFuzzyMatch("", _) ->
	?FALSE;
stringFuzzyMatch(_, "") ->
	?FALSE;
stringFuzzyMatch(P, S)when not is_list(P) orelse not is_list(S) ->
	?FALSE;
stringFuzzyMatch(P, S) ->
	try
		case hd(P) == hd(S) of
			?TRUE ->
				Len = length(P),
				S1 = lists:sublist(S, 1, Len),
				case P == S1 of
					?TRUE -> ?TRUE;
					_ -> stringFuzzyMatch(P, tl(S))
				end;
			_ -> stringFuzzyMatch(P, tl(S))
		end
	catch
		_:_ -> stringFuzzyMatch(P, tl(S))
	end.

dropRecordName(Record) ->
	[_|T] = erlang:tuple_to_list(Record),
	erlang:list_to_tuple(T).
attachRecordName(Tuple,RecordName) ->
	List = erlang:tuple_to_list(Tuple),
	erlang:list_to_tuple([RecordName|List]).

eval(Str) ->
	{ok,Ts,_} = erl_scan:string(Str),
	Ts1 = case lists:reverse(Ts) of
		      [{dot,_}|_] -> Ts;
		      TsR -> lists:reverse([{dot,1} | TsR])
	      end,
	{ok,Expr} = erl_parse:parse_exprs(Ts1),
	{value,Value,_}=erl_eval:exprs(Expr, []),
	Value.

getServerID() ->
	data_setting:get(server_id).

%%在有序的列表PlayerRankList里面，插入数据，二分法排序
%%IsAddOldValue是否加上PlayerRankList列表里面原本PlayerID的值OldValue
%%PlayerRankList::UpdateList::DelList::[{Rank,PlayerID,Value}]
%%return {NewPlayerRankList,UpdateList,DelList}
%%效率比起lists:sort低些，但是能返回变动的数据
calcRankUpdate(RoleID, AddValue, BeforeData,PlayerRankList, RankMax, RankIndex, PlayerIDIndex, ValueIndex, IsAddOldValue) ->
	case lists:keyfind(RoleID,PlayerIDIndex,PlayerRankList) of
		OldData when is_tuple(OldData) ->
			Rank = element(RankIndex,OldData),
			OldValue = element(ValueIndex,OldData),
			BeforeValue = element(ValueIndex,BeforeData),
			NewValue = ?IF(IsAddOldValue,max(OldValue,BeforeValue) + AddValue,AddValue),
			case Rank of
				1 ->%%已经是第一名
					NewData = updateTupleValue(BeforeData, [{RankIndex,1},{ValueIndex,NewValue}]),
					{lists:keyreplace(RoleID,PlayerIDIndex,PlayerRankList,NewData),[NewData],[]};
				_ ->
					case lists:split(Rank-1,PlayerRankList) of
						{HeadList,[_|TailList]} ->%%把自己的排名过滤掉，因为自己要到HeadList里面去了
							{HeadList1,NewRank,TailList1} = insertRankList(HeadList, NewValue, ValueIndex),
							{UpdateList,DelList}=backwardPlayerRankList(TailList1, RankMax, RankIndex),
							NewData = updateTupleValue(BeforeData,[{RankIndex,NewRank},{ValueIndex,NewValue}]),
							PlayerRankList1 = HeadList1++[NewData|UpdateList]++TailList,
							{PlayerRankList1,[NewData|UpdateList],DelList};
						_ ->
							{HeadList1,NewRank,TailList1} = insertRankList(PlayerRankList, NewValue, ValueIndex),
							{UpdateList,DelList}=backwardPlayerRankList(TailList1, RankMax, RankIndex),
							NewData = updateTupleValue(BeforeData,[{RankIndex,NewRank},{ValueIndex,NewValue}]),
							PlayerRankList1 = HeadList1++[NewData|UpdateList],
							{PlayerRankList1,[NewData|UpdateList],DelList}
					end
			end;
		?FALSE ->%%新进排名
			BeforeValue = element(ValueIndex,BeforeData),
			NewValue = AddValue + BeforeValue,
			{HeadList1,NewRank,TailList1} = insertRankList(PlayerRankList, NewValue, ValueIndex),
			case NewRank>RankMax of
				?TRUE ->%%没有加入进来
					{PlayerRankList, [], []};
				_ ->
					{UpdateList,DelList}=backwardPlayerRankList(TailList1, RankMax, RankIndex),
					NewData = updateTupleValue(BeforeData,[{RankIndex,NewRank},{ValueIndex,NewValue}]),
					PlayerRankList1 = HeadList1++[NewData|UpdateList],
					{PlayerRankList1,[NewData|UpdateList],DelList}
			end
	end.

insertRankList(PlayerRankList, Value, ValueIndex) ->
	Len =length(PlayerRankList),
	Split = util:specialTruncRound(Len / 2),
	{HeadList,TailList}=lists:split(Split,PlayerRankList),
	{HeadList1,Rank,TailList1}=doInsertRankList(HeadList,TailList, Value,[],[], ValueIndex),
	{HeadList1,Rank,TailList1}.
%%HeadList里面不一定都比自己高， TailList 里面不一定都比自己低
doInsertRankList([],[Data|_T]=TailList, Honor,FinalHeadList,FinalTailList, ValueIndex)when element(ValueIndex,Data)<Honor ->
	{FinalHeadList,length(FinalHeadList)+1,TailList++FinalTailList};
doInsertRankList([],[Data|T], Honor,FinalHeadList,FinalTailList, ValueIndex)when element(ValueIndex,Data)>Honor ->
	Len =length(T),
	Split = util:specialTruncRound(Len / 2),
	{HeadList1,TailList1}=lists:split(Split,T),
	doInsertRankList(HeadList1,TailList1,Honor,FinalHeadList++[Data],FinalTailList, ValueIndex);
doInsertRankList([],[Data|T], Honor,FinalHeadList,FinalTailList, ValueIndex) ->%%相等
	Len =length(T),
	Split = util:specialTruncRound(Len / 2),
	{HeadList1,TailList1}=lists:split(Split,T),
	doInsertRankList(HeadList1,TailList1,Honor,FinalHeadList++[Data],FinalTailList, ValueIndex);
doInsertRankList([Data|_T]=HeadList,[], Honor,FinalHeadList,FinalTailList, ValueIndex)when element(ValueIndex,Data)<Honor ->
	{FinalHeadList,length(FinalHeadList)+1,HeadList++FinalTailList};
doInsertRankList([Data|T],[], Honor,FinalHeadList,FinalTailList, ValueIndex)when element(ValueIndex,Data)>Honor ->
	Len =length(T),
	Split = util:specialTruncRound(Len / 2),
	{HeadList1,TailList1}=lists:split(Split,T),
	doInsertRankList(HeadList1,TailList1,Honor,FinalHeadList++[Data],FinalTailList, ValueIndex);
doInsertRankList([Data|T],[], Honor,FinalHeadList,FinalTailList, ValueIndex) ->%%相等
	Len =length(T),
	Split = util:specialTruncRound(Len / 2),
	{HeadList1,TailList1}=lists:split(Split,T),
	doInsertRankList(HeadList1,TailList1,Honor,FinalHeadList++[Data],FinalTailList, ValueIndex);
doInsertRankList(HeadList,[], _Honor,FinalHeadList,FinalTailList, _ValueIndex) ->
	HeadList1 = FinalHeadList++HeadList,
	{HeadList1,length(HeadList1)+1,FinalTailList};
doInsertRankList(HeadList,[Data|_T]=TailList, Honor,FinalHeadList,FinalTailList, ValueIndex)when element(ValueIndex,Data)<Honor ->
	Len =length(HeadList),
	Split = Len div 2,
	{HeadList1,TailList1}=lists:split(Split,HeadList),
	doInsertRankList(HeadList1,TailList1,Honor,FinalHeadList,TailList++FinalTailList, ValueIndex);
doInsertRankList(HeadList,[Data|_T]=TailList, Honor,FinalHeadList,FinalTailList, ValueIndex)when element(ValueIndex,Data)>Honor ->
	Len =length(TailList),
	Split = util:specialTruncRound(Len / 2),
	{HeadList1,TailList1}=lists:split(Split,TailList),
	doInsertRankList(HeadList1,TailList1,Honor,FinalHeadList++HeadList,FinalTailList, ValueIndex);
doInsertRankList(HeadList,[Data|T], Honor,FinalHeadList,FinalTailList, ValueIndex) ->%%相等
	Len =length(T),
	Split = util:specialTruncRound(Len / 2),
	{HeadList1,TailList1}=lists:split(Split,T),
	doInsertRankList(HeadList1,TailList1,Honor,FinalHeadList++HeadList++[Data],FinalTailList, ValueIndex).

%%所有排名向后移动一位
%%return {UpdateList, DelList}
backwardPlayerRankList(PlayerRankList, RankMax, RankIndex) ->
	{UpdateList,DelList}=lists:foldr(fun(Data,{AccUpdateList,AccDelList}) ->
		Rank = element(RankIndex,Data),
		case Rank>= RankMax of
			?TRUE -> {AccUpdateList,[Data|AccDelList]};
			_ -> {[setelement(RankIndex,Data,Rank+1)|AccUpdateList],AccDelList}
		end
	                                 end,{[],[]},PlayerRankList),
	{UpdateList,DelList}.

updateTupleValue(OldTuple, UpdateList) ->
	lists:foldl(fun({Index, Value}, AccData) ->
		setelement(Index, AccData, Value) end, OldTuple, UpdateList).

format_utf8([],AccList)->
	lists:reverse(AccList);
format_utf8([H|L],AccList) when is_integer(H)->
	if
		H >= 16#100 andalso H =< 16#FFFF ->    %% Unicode 编码
			format_utf8(L,lists:reverse(binary_to_list(unicode:characters_to_binary([H]))) ++ AccList);
		true -> format_utf8(L,[H|AccList])
	end;
format_utf8([H|L],AccList) when is_list(H)->
	format_utf8(L,[format_utf8(H)|AccList]).

format_utf8(Bin) when is_binary(Bin)->
	Bin;    %% 这个匹配项不符合规范，但是需要兼容旧代码
format_utf8(Str) when is_list(Str)->
	format_utf8(Str,[]).